package com.zc.timedown.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zc.common.utils.DateUtils;
import com.zc.common.utils.StringUtils;
import com.zc.common.utils.UserThreadLocal;

import com.zc.timedown.constants.AchievementTypeConstants;
import com.zc.timedown.dto.*;
import com.zc.timedown.domain.*;
import com.zc.timedown.mapper.TodayGoalMapper;
import com.zc.timedown.mapper.TodayPlanMapper;
import com.zc.timedown.mapper.UserMapper;
import com.zc.timedown.service.ApiAchievementService;
import com.zc.timedown.service.ApiTodayPlanService;
import com.zc.timedown.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 今日计划Service业务层处理
 *
 * @author zc
 * @date 2025-09-30
 */
@Service
public class ApiTodayPlanServiceImpl extends ServiceImpl<TodayPlanMapper, TodayPlan> implements ApiTodayPlanService
{
    @Autowired
    private TodayPlanMapper todayPlanMapper;

    @Autowired
    private TodayGoalMapper todayGoalMapper;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ApiAchievementService achievementService;

    /**
     * 获取今日计划
     *
     * @param userId
     * @return 结果
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TodayPlanVo getDailyPlan(Long userId) {
        TodayPlan todayPlanDto = new TodayPlan();
        todayPlanDto.setUserId(userId);
        List<TodayPlan> plans = todayPlanMapper.selectTodayPlanList(todayPlanDto);
        // 判断计划是否存在,创建过计划
        if (plans != null && !plans.isEmpty()){
            todayPlanDto.setPlanDate(LocalDate.now());
            List<TodayPlan> todayPlans = todayPlanMapper.selectTodayPlanList(todayPlanDto);

            //判断当天是否创建过计划，
            if (todayPlans != null && !todayPlans.isEmpty()){
                //当天创建过计划，直接返回主计划及子计划列表
                TodayPlanVo todayPlanVo = new TodayPlanVo();
                TodayPlan todayPlan = todayPlans.get(0);
                todayPlanVo.setTodayPlan(todayPlan);
                List<TodayPlanItemVo> todayPlanItemVos = todayPlanMapper.selectTodayPlanByIdAndDate(todayPlan.getId());
                if (todayPlanItemVos != null && !todayPlanItemVos.isEmpty()){
                    todayPlanVo.setTodayPlanItems(todayPlanItemVos);
                }else {
                    todayPlanVo.setTodayPlanItems(new ArrayList<>());
                }
                return todayPlanVo;
            }else{
                //创建今日计划，添加今日计划子列表
                TodayPlan todayPlanReq = new TodayPlan();
                todayPlanReq.setCreateTime(DateUtils.getNowDate());
                todayPlanReq.setPlanDate(LocalDate.now());
                todayPlanReq.setUserId(userId);
                //创建今日主计划
                todayPlanMapper.insert(todayPlanReq);
                // 插入后可以直接获取ID
                Long planId = todayPlanReq.getId();
                TodayGoal todayGoalReq = new TodayGoal();
                todayGoalReq.setUserId(userId);
                //获取今日目标列表
                List<TodayGoal> todayGoals = todayGoalMapper.selectTodayGoalList(todayGoalReq);
                //修改今日计划主表
                todayPlanReq.setTotalGoals(todayGoals.size());
                todayPlanReq.setCompletedCount(0);
                todayPlanReq.setCompletionRate(BigDecimal.ZERO);
                todayPlanMapper.updateById(todayPlanReq);

                if (todayGoals != null && !todayGoals.isEmpty()){
                    ArrayList<TodayPlanItem> todayPlanItems = new ArrayList<>();
                    for (TodayGoal todayGoal : todayGoals) {
                        TodayPlanItem todayPlanItem = new TodayPlanItem();
                        todayPlanItem.setPlanId(planId);
                        todayPlanItem.setGoalId(todayGoal.getId());
                        todayPlanItem.setIsCompleted(0);
                        todayPlanItem.setCreateTime(DateUtils.getNowDate());
                        todayPlanItems.add(todayPlanItem);
                    }
                    //批量创建今日计划子列表
                    todayPlanMapper.batchTodayPlanItem(todayPlanItems);
                }

                TodayPlan todayPlan = todayPlanMapper.selectById(planId);

                List<TodayPlanItemVo> todayPlanItemVos = todayPlanMapper.selectTodayPlanByIdAndDate(todayPlan.getId());
                //创建返回Vo
                TodayPlanVo todayPlanVo = new TodayPlanVo();
                todayPlanVo.setTodayPlan(todayPlan);
                if (todayPlanItemVos != null && !todayPlanItemVos.isEmpty()){
                    todayPlanVo.setTodayPlanItems(todayPlanItemVos);
                }else {
                    todayPlanVo.setTodayPlanItems(new ArrayList<>());
                }
                return todayPlanVo;
            }

        }else{
            //计划不存在，没有创建过计划
            //创建第一次今日计划，添加默认的今日目标
            TodayPlan todayPlanReq = new TodayPlan();
            todayPlanReq.setCreateTime(DateUtils.getNowDate());
            todayPlanReq.setPlanDate(LocalDate.now());
            todayPlanReq.setUserId(userId);
            //修改今日计划主表
            todayPlanReq.setTotalGoals(4);
            todayPlanReq.setCompletedCount(0);
            todayPlanReq.setCompletionRate(BigDecimal.ZERO);
            todayPlanMapper.insert(todayPlanReq);
            // 插入后可以直接获取ID
            Long planId = todayPlanReq.getId();

            //创建今日目标列表
            List<TodayGoal> goals = new ArrayList<>();
            // 创建第一个目标
            TodayGoal goal1 = new TodayGoal();
            goal1.setName("晨跑30分钟");
            goal1.setDescription("唤醒身体活力，提升免疫力");
            goal1.setCategory("健康");
            goal1.setIcon("🏃");
            goal1.setUserId(userId);
            goal1.setCreateTime(DateUtils.getNowDate());
            goal1.setIsEnabled(1);
            goals.add(goal1);

            // 创建第二个目标
            TodayGoal goal2 = new TodayGoal();
            goal2.setName("喝水八杯");
            goal2.setDescription("养成良好的饮水习惯");
            goal2.setCategory("健康");
            goal2.setIcon("💧");
            goal2.setUserId(userId);
            goal2.setIsEnabled(1);
            goal2.setCreateTime(DateUtils.getNowDate());
            goals.add(goal2);


            // 创建第三个目标
            TodayGoal goal3 = new TodayGoal();
            goal3.setName("整理办公桌");
            goal3.setDescription("清理杂物提高工作效率");
            goal3.setCategory("工作");
            goal3.setIcon("💻");
            goal3.setIsEnabled(1);
            goal3.setUserId(userId);
            goal3.setCreateTime(DateUtils.getNowDate());
            goals.add(goal3);

            // 创建第四个目标
            TodayGoal goal4 = new TodayGoal();
            goal4.setName("阅读技术文章一篇");
            goal4.setDescription("关注前沿知识和技术动态");
            goal4.setCategory("学习");
            goal4.setIcon("📚");
            goal4.setIsEnabled(1);
            goal4.setUserId(userId);
            goal4.setCreateTime(DateUtils.getNowDate());
            goals.add(goal4);


            ArrayList<TodayPlanItem> todayPlanItems = new ArrayList<>();
            // 插入数据库
            for (TodayGoal goal : goals) {
                todayGoalMapper.insert(goal);
                Long goalId = goal.getId();
                System.out.println("插入的目标ID: " + goalId);
                TodayPlanItem todayPlanItem = new TodayPlanItem();
                todayPlanItem.setPlanId(planId);
                todayPlanItem.setGoalId(goalId);
                todayPlanItem.setIsCompleted(0);
                todayPlanItem.setCreateTime(DateUtils.getNowDate());
                todayPlanItems.add(todayPlanItem);
            }
            //批量创建今日目标子列表
            todayPlanMapper.batchTodayPlanItem(todayPlanItems);

            List<TodayPlanItemVo> todayPlanItemVos = todayPlanMapper.selectTodayPlanByIdAndDate(todayPlanReq.getId());
            //创建返回Vo
            TodayPlanVo todayPlanVo = new TodayPlanVo();
            todayPlanVo.setTodayPlan(todayPlanReq);
            if (todayPlanItemVos != null && !todayPlanItemVos.isEmpty()){
                todayPlanVo.setTodayPlanItems(todayPlanItemVos);
            }else {
                todayPlanVo.setTodayPlanItems(new ArrayList<>());
            }
            return todayPlanVo;
        }

    }





    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTodayPlanItem(TodayPlanItemDto todayPlanItemDto) {
        TodayPlan plan = todayPlanMapper.selectTodayPlanById(todayPlanItemDto.getPlanId());
        int completed = 0;
        if (plan != null && plan.getCompletionRate() != null && plan.getCompletionRate().compareTo(BigDecimal.ONE) == 0){
            //今日计划已全部完成
            completed = 1;
            throw new RuntimeException("今日目标已全部完成");
        }


        int row = todayPlanMapper.updateTodayPlanItem(todayPlanItemDto);
         updateTodayPlan(todayPlanItemDto.getPlanId(), completed);
        return row;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertTodayGoalAndPlanItem(TodayGoal todayGoal) {

        todayGoal.setCreateTime(DateUtils.getNowDate());
        int row = todayGoalMapper.insert(todayGoal);

        TodayPlan todayPlanDto = new TodayPlan();
        todayPlanDto.setUserId(todayGoal.getUserId());
        todayPlanDto.setPlanDate(LocalDate.now());
        List<TodayPlan> todayPlans = todayPlanMapper.selectTodayPlanList(todayPlanDto);
        if (todayPlans == null || todayPlans.isEmpty()){
            throw new RuntimeException("今日计划不存在");
        }

        TodayPlan todayPlan = todayPlans.get(0);

        if (todayPlan != null && todayPlan.getCompletionRate() != null && todayPlan.getCompletionRate().compareTo(BigDecimal.ONE) == 0){
            //今日目标已全部完成
            throw new RuntimeException("今日目标已全部完成");
        }


        if (row > 0){

            TodayPlanItem todayPlanItem = new TodayPlanItem();
            todayPlanItem.setGoalId(todayGoal.getId());
            todayPlanItem.setPlanId(todayPlan.getId());
            todayPlanItem.setIsCompleted(0);
            todayPlanItem.setCreateTime(DateUtils.getNowDate());
            todayPlanMapper.batchTodayPlanItem(Arrays.asList(todayPlanItem));
            updateTodayPlan(todayPlan.getId(),0);
        }
        return row;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int delTodayGoalAndPlanItem(TodayPlanItemDto todayPlanItemDto) {
        TodayPlan plan = todayPlanMapper.selectTodayPlanById(todayPlanItemDto.getPlanId());
        int completed = 0;
        if (plan != null && plan.getCompletionRate() != null && plan.getCompletionRate().compareTo(BigDecimal.ONE) == 0){
            //今日计划已全部完成
            TodayGoal todayGoal = todayGoalMapper.selectTodayGoalById(todayPlanItemDto.getGoalId());
            if (todayGoal.getIsEnabled() == 1){
                throw new RuntimeException("今日目标已全部完成");
            }
            completed = 1;

        }
        int row2 = todayPlanMapper.deleteTodayPlanItem(todayPlanItemDto.getPlanItemId());
        int row = todayGoalMapper.deleteTodayGoalById(todayPlanItemDto.getGoalId());
        updateTodayPlan(todayPlanItemDto.getPlanId(),completed);
        return row2;
    }

    @Override
    public List<WeeklyPlanStatisticsVo> getWeeklyPlanStatistics(Long userId) {
        return todayPlanMapper.selectWeeklyPlanStatistics(userId);
    }

    @Override
    public List<DailyCompletedStatisticsVo> getMonthlyCompletedStatistics(Long userId) {
        return todayPlanMapper.selectMonthlyCompletedStatistics(userId);
    }

    @Override
    public List<WeeklyStatsVO> getRecent4WeeksStats() {
        Long userId = UserThreadLocal.getUserId();
        List<WeeklyStatsDTO> statsList = todayPlanMapper.selectRecent4WeeksStats(userId);
        return statsList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<MonthlyStatsVo> getMonthlyClockInStats(Long userId, Integer year, Integer month) {
        List<MonthlyStatsDTO> statsList = todayPlanMapper.selectMonthlyClockInStatsByMonth(userId, year, month);
        return statsList.stream()
                .map(this::convertToMonthlyStatsVO)
                .collect(Collectors.toList());
    }

    @Override
    public AllStats selectAllClockInStats(Long userId) {
        return todayPlanMapper.selectAllClockInStats(userId);
    }

    @Override
    public TimeRangeStatisticsVo getTimeRangeStats(Long userId, String startDate, String endDate) {
        TimeRangeStatisticsDto dto = todayPlanMapper.selectTimeRangeStats(userId, startDate, endDate);
        TimeRangeStatisticsVo vo = new TimeRangeStatisticsVo();
        if (dto != null) {
            vo.setTotalGoals(dto.getTotalGoals());
            vo.setCompletedGoals(dto.getCompletedGoals());
            vo.setCompletionRate(dto.getCompletionRate());
            vo.setClockInDays(dto.getClockInDays());
            vo.setTotalDays(dto.getTotalDays());
            vo.setStartDate(dto.getStartDate());
            vo.setEndDate(dto.getEndDate());
        }
        return vo;
    }

    private MonthlyStatsVo convertToMonthlyStatsVO(MonthlyStatsDTO dto) {
        MonthlyStatsVo vo = new MonthlyStatsVo();
        vo.setMonthKey(dto.getMonthKey());
        vo.setMonthName(dto.getMonthName());
        vo.setClockInDays(dto.getClockInDays());
        vo.setTotalDays(dto.getTotalDays());
        vo.setCompletionPercentage(dto.getCompletionPercentage());
        return vo;
    }

    /**
     * 将 DTO 转换为 VO
     */
    private WeeklyStatsVO convertToVO(WeeklyStatsDTO dto) {
        WeeklyStatsVO vo = new WeeklyStatsVO();
        vo.setWeekStartDate(dto.getWeekStartDate());
        vo.setWeekEndDate(dto.getWeekEndDate());
        vo.setClockInDays(dto.getClockInDays());
        vo.setTotalGoals(dto.getTotalGoals());
        vo.setCompletedGoals(dto.getCompletedGoals());
        if (dto.getTotalGoals() > 0) {
            vo.setCompletionRate(BigDecimal.valueOf((double) dto.getCompletedGoals() / dto.getTotalGoals() * 100)
                    .setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setCompletionRate(BigDecimal.ZERO);
        }
        return vo;
    }


    /**
     * 查询今日计划
     *
     * @param id 今日计划主键
     * @return 今日计划
     */
    @Override
    public TodayPlan selectTodayPlanById(Long id)
    {
                return getById(id);
    }

    /**
     * 查询今日计划列表
     *
     * @param todayPlan 今日计划
     * @return 今日计划
     */
    @Override
    public List<TodayPlan> selectTodayPlanList(TodayPlan todayPlan)
    {
        return todayPlanMapper.selectTodayPlanList(todayPlan);
    }

    /**
     * 新增今日计划
     *
     * @param todayPlan 今日计划
     * @return 结果
     */
        @Transactional
    @Override
    public int insertTodayPlan(TodayPlan todayPlan)
    {

           todayPlan.setCreateTime(DateUtils.getNowDate());
            int rows = todayPlanMapper.insertTodayPlan(todayPlan);
            insertTodayPlanItem(todayPlan);
            return rows;
    }

    /**
     * 修改今日计划
     *
     * @param todayPlan 今日计划
     * @return 结果
     */
        @Transactional
    @Override
    public int updateTodayPlan(TodayPlan todayPlan)
    {

                todayPlan.setUpdateTime(DateUtils.getNowDate());
                todayPlanMapper.deleteTodayPlanItemByGoalId(todayPlan.getId());
                insertTodayPlanItem(todayPlan);
                return updateById(todayPlan) == true ? 1 : 0;
    }

    /**
     * 批量删除今日计划
     *
     * @param ids 需要删除的今日计划主键
     * @return 结果
     */
        @Transactional
    @Override
    public int deleteTodayPlanByIds(Long[] ids)
    {
                todayPlanMapper.deleteTodayPlanItemByGoalIds(ids);
                return removeByIds(Arrays.asList(ids)) == true ? 1 : 0;
    }

    /**
     * 删除今日计划信息
     *
     * @param id 今日计划主键
     * @return 结果
     */
        @Transactional
    @Override
    public int deleteTodayPlanById(Long id)
    {
                todayPlanMapper.deleteTodayPlanItemByGoalId(id);
                return removeById(id) == true ? 1 : 0;
    }



    /**
         * 新增今日计划子项明细信息
         *
         * @param todayPlan 今日计划对象
         */
        public void insertTodayPlanItem(TodayPlan todayPlan)
        {
            List<TodayPlanItem> todayPlanItemList = todayPlan.getTodayPlanItemList();
            Long id = todayPlan.getId();
            if (StringUtils.isNotNull(todayPlanItemList))
            {
                List<TodayPlanItem> list = new ArrayList<TodayPlanItem>();
                for (TodayPlanItem todayPlanItem : todayPlanItemList)
                {
                    todayPlanItem.setGoalId(id);
                    list.add(todayPlanItem);
                }
                if (list.size() > 0)
                {
                        todayPlanMapper.batchTodayPlanItem(list);
                }
            }
        }


    /**
     * 更新今日计划主表中计划项信息
 }
     *
     * @param planId 今日计划对象
     */
    public void updateTodayPlan(Long planId, int isCompleted)
    {

        Long userId = UserThreadLocal.getUserId();
        List<TodayPlanItemVo> todayPlanItemVos = todayPlanMapper.selectTodayPlanByIdAndDate(planId);
        List<TodayPlanItemVo> collects = todayPlanItemVos.stream()
                .filter(todayPlanItemVo -> todayPlanItemVo.getIsEnabled() .equals(1))
                .collect(Collectors.toList());
// 使用Stream计算已完成的计划项个数
        long completedCount = collects.stream()
                .filter(item -> item.getIsCompleted().equals(1))
                .count();
        TodayPlan todayPlan = new TodayPlan();
        todayPlan.setId(planId);
        todayPlan.setCompletedCount(Math.toIntExact(completedCount));
        todayPlan.setTotalGoals(collects.size());
        if (collects.size() <= 0){
            todayPlan.setCompletionRate(BigDecimal.ZERO);
        }else {
            todayPlan.setCompletionRate(new BigDecimal(completedCount).divide(new BigDecimal(collects.size()), 4, RoundingMode.HALF_UP));
        }

        todayPlanMapper.updateById(todayPlan);
        TodayPlan plan = todayPlanMapper.selectTodayPlanById(planId);
        int updateComplete = 0;
        if (plan != null && plan.getCompletionRate() !=null && plan.getCompletionRate().compareTo(BigDecimal.ONE) == 0) {
           updateComplete = 1;
        }

        int updateCount = 0;
        if (isCompleted == 0 && updateComplete == 1){
            updateCount = 1;
        }else if (isCompleted == 1 && updateComplete == 0){
            updateCount = -1;
        }

        if(updateCount != 0){
            User user = userMapper.selectUserById(userId);
            //当前连击数
            Integer currentStreak = user.getCurrentStreak();
            //最大连击数
            Integer maxStreak = user.getMaxStreak();
            if(isYesterdayPlanCompleted(userId)){
                currentStreak = currentStreak + updateCount;
                if(currentStreak > maxStreak){
                    maxStreak = currentStreak;
                }

            }else {
                if (updateCount == -1){
                    currentStreak = 0;
                }else {
                    currentStreak = 1;
                    if (maxStreak == 0){
                        maxStreak = 1;
                    }
                }

            }
            user.setCurrentStreak(currentStreak);
            user.setMaxStreak(maxStreak);
            userMapper.updateUser(user);

            // 修正判断逻辑
            if (currentStreak == 3 || currentStreak == 7 || currentStreak == 14
                    || currentStreak == 30 || currentStreak == 100 || currentStreak == 365) {
                // 创建成就记录
                insertAchievement(userId, currentStreak);
            }

        }

    }


    private void insertAchievement(Long userId, int currentStreak) {
        Achievement achievement = new Achievement();
        achievement.setUserId(userId);
        achievement.setAchievedDate(LocalDateTime.now());
        if (currentStreak == 3){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_3_DAYS);
        }else if (currentStreak == 7){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_7_DAYS);
        }else if (currentStreak == 14){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_14_DAYS);
        }else if (currentStreak == 30){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_30_DAYS);
        }else if (currentStreak == 100){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_100_DAYS);
        }else if (currentStreak == 365){
            achievement.setAchievementType(AchievementTypeConstants.CONSECUTIVE_365_DAYS);
        }
        achievementService.insertAchievement(achievement);
    }



    /**
     * 查询用户昨天是否完成了今日计划
     * @param userId 用户ID
     * @return true表示完成，false表示未完成
     */
    private boolean isYesterdayPlanCompleted(Long userId) {
        // 构造查询条件
        TodayPlan queryPlan = new TodayPlan();
        queryPlan.setUserId(userId);
        queryPlan.setPlanDate(DateUtils.getYesterday());
        // 查询昨天的计划
        List<TodayPlan> yesterdayPlans = todayPlanMapper.selectTodayPlanList(queryPlan);

        // 如果昨天没有创建计划，则视为未完成
        if (yesterdayPlans == null || yesterdayPlans.isEmpty()) {
            return false;
        }

        // 获取昨天的计划
        TodayPlan yesterdayPlan = yesterdayPlans.get(0);

        // 检查完成数量是否大于0且完成率是否大于0
        if (yesterdayPlan.getCompletionRate() != null && yesterdayPlan.getCompletionRate().compareTo(BigDecimal.ONE) == 0) {
            return true;
        }

        return false;

    }

    @Override
    public List<DailyPlanStatisticsVo> getDailyPlanStatistics(Long userId, String startDate, String endDate) {
        List<DailyPlanStatisticsDto> dtoList = todayPlanMapper.selectDailyPlanStatistics(userId, startDate, endDate);
        return dtoList.stream().map(dto -> {
            DailyPlanStatisticsVo vo = new DailyPlanStatisticsVo();
            vo.setDate(dto.getDate());
            vo.setWeekDay(dto.getWeekDay());
            vo.setCompletedCount(dto.getCompletedCount() != null ? dto.getCompletedCount() : 0);
            vo.setTotalGoals(dto.getTotalGoals() != null ? dto.getTotalGoals() : 0);
            vo.setCompletionRate(dto.getCompletionRate() != null ? dto.getCompletionRate() : BigDecimal.ZERO);
            return vo;
        }).collect(Collectors.toList());
    }







}